package values.item
{
import flash.errors.IllegalOperationError;

import isoengine.interfaces.IMapObjectData;

import values.building.FinalBuildFriendCostPositionValue;
import values.common.CostValue;
import values.events.BuildingItemValueEvent;
import values.events.ItemValueEvent;
import values.item.building.BuildingUpgradeRequirementValue;

/**
 * BuildingItemValue
 * @author jliang
 *
 */
public class BuildingItemValue extends ItemValue implements IUpgradebleItemValue, IMapObjectData
{
	//==========================================================================
	//  Constructor
	//==========================================================================
	public function BuildingItemValue()
	{
		super();
	}
	//==========================================================================
	//  Properties
	//==========================================================================
	public function get mapObjectClassRef():Class
	{
		throw new IllegalOperationError("mapObjectClassRef getter should be overrided.");
	}
	
	public function get buildingTemplate():BuildingItemTemplateValue
	{
		return BuildingItemTemplateValue(template);
	}	

	public function get buildProgress():int
	{
		return params.progress;
	}

	public function set buildProgress(value:int):void
	{
		params.progress = value;
		
		if (!isUnderConstruction)
		{
			_finalBuildFriend = null;
		}
	}
	
	public function get buildCount():int
	{
		return buildingTemplate.buildCount;
	}
	
	public function get buildCost():CostValue
	{
		if (!isUnderConstruction) return new CostValue();
		
		if (buildProgress + 1 < buildCount)
		{
			return buildingTemplate.buildCost;
		}
		else
		{
			return buildingTemplate.finalBuildResourceCost;
		}
	}
	
	public function get isUnderConstruction():Boolean
	{
		return buildingTemplate.buildCount <= 0 ? false : buildProgress < buildingTemplate.buildCount;
	}
	
	public function get type():String
	{
		return "building";
	}
	
	public function get width():int
	{
		return buildingTemplate.width;
	}
	
	public function get height():int
	{
		return buildingTemplate.height;
	}
	
	public function set x(value:int):void
	{
		params.x = value;
	}
	
	public function get x():int
	{
		return params.x;
	}
	
	public function set y(value:int):void
	{
		params.y = value;
	}
	
	public function get y():int
	{
		return params.y;
	}
	
	protected var _walkable:Boolean;
	
	public function set walkable(value:Boolean):void
	{
		_walkable = value;
	}
	
	public function get walkable():Boolean
	{
		return _walkable;
	}
	
	public function set direction(value:int):void
	{
		params.direction = value;
	}
	
	public function get direction():int
	{
		return params.direction;
	}
	
	public function set state(value:int):void
	{
		params.state = value;
	}
	
	public function get state():int
	{
		return params.state;
	}
	
	public function get currentState():BuildingStateValue
	{
		return buildingTemplate.getStateByKey(state);
	}
	
	protected var _finalBuildFriend:Vector.<FinalBuildFriendCostPositionValue>;

	public function get finalBuildFriend():Vector.<FinalBuildFriendCostPositionValue>
	{
		return _finalBuildFriend;
	}
	
	public function get speicalParams():Object
	{
		return params.params;
	}
	
	public function get nextLevelRequirement():BuildingUpgradeRequirementValue
	{
		return buildingTemplate.getUpgradeRequirementByLevel(level + 1);
	}
	
	public function get nextLevelCost():CostValue
	{
		return buildingTemplate.getUpgradeByLevel(level + 1).cost;
	}
	//==========================================================================
	//  Overridden methods: ItemValue
	//==========================================================================
	override public function initialize(params:*):void
	{
		super.initialize(params);
		
		if (!this.params.hasOwnProperty("level"))
		{
			setLevel(1);
		}
		if (!this.params.hasOwnProperty("progress"))
		{
			buildProgress = 0;
		}
		if (!this.params.hasOwnProperty("state"))
		{
			state = 0;
		}
		if (!this.params.hasOwnProperty("direction"))
		{
			direction = 0;
		}
		if (!this.params.hasOwnProperty("x"))
		{
			x = 0;
		}
		if (!this.params.hasOwnProperty("y"))
		{
			y = 0;
		}
        
        if (!this.params.hasOwnProperty("final_build_friends"))
        {
            this.params.final_build_friends = {};
        }
        
        _finalBuildFriend = new Vector.<FinalBuildFriendCostPositionValue>();
        
		if (isUnderConstruction &&
			buildingTemplate.finalBuildFriendCost.positions.length > 0)
		{						
			for each (var vo:FinalBuildFriendCostPositionValue in buildingTemplate.finalBuildFriendCost.positions)
			{
				var fbfcpvo:FinalBuildFriendCostPositionValue = vo.clone();
				finalBuildFriend.push(fbfcpvo);
				if (this.params.hasOwnProperty("final_build_friends"))
				{
					var pid:String = String(this.params.final_build_friends[fbfcpvo.index]);
					if (pid != null && pid != "" && pid != "undefined")
					{
						fbfcpvo.playerID = pid;
					}
				}
			}
		}
		
		if (!this.params.hasOwnProperty("params"))
		{
			this.params.params = {};
		}
		
		_walkable = buildingTemplate.walkable;
	}
	
	override public function equals(value:IItemValue):Boolean
	{
		if (key != value.key) return false;
		
		if (level != IUpgradebleItemValue(value).level) return false;
		
		if (buildProgress != BuildingItemValue(value).buildProgress) return false;
		
		return true;
	}
	
	override public function toObject():Object
	{
		//obj = { key:template.key, db_key:template.dbKey, uid:uid };
		var obj:Object = super.toObject(); 
		obj.push({
			level: level,
			progress: buildProgress,
			state: state,
			x:x,
			y:y,
            final_build_friends: params.final_build_friends
		});
		return obj;
	}
	//==========================================================================
	//  Public methods
	//==========================================================================
	public function isMatchParams(obj:Object):Boolean
	{
		return level == obj.level && buildProgress == obj.progress && state == obj.state;
	}
	//==========================================================================
	//  interface - IUpgradebleItemValue
	//==========================================================================	
	protected function setLevel(value:int):void
	{
		params.level = value;
	}
	
	public function get level():int
	{
		return params.level;
	}
	
	public function get isMaxLevel():Boolean
	{
		return level == buildingTemplate.maxLevel;
	}
	
	public function get currentUpgradeValue():ItemUpgradeValue
	{
		return buildingTemplate.getUpgradeByLevel(level);
	}
	
	public function setUpgradeCondition(...args):Boolean
	{
		var result:int = checkUpgradeCondition.apply(this, args);
		var evt:ItemValueEvent;
		var oldValue:int = level;
		if (result > 0)
		{
			evt = new ItemValueEvent(ItemValueEvent.UPGRADED_SUCCESS);
			setLevel(level + result);
		}
		else
		{
			evt = new ItemValueEvent(ItemValueEvent.UPGRADED_FAIL);
		}		
		evt.params = { item:this, oldValue:oldValue, newValue:level };
		this.dispatchEvent(evt);
        
        return result > 0;
	}
	
	protected function checkUpgradeCondition(...args):int
	{
		return 1;
	}
	
	public function build():void
	{
		var evt:BuildingItemValueEvent = new BuildingItemValueEvent(BuildingItemValueEvent.BUILD);
		evt.params = { item:this, cost:buildCost };
		this.dispatchEvent(evt);
	}
}
}




